package com.zyj.demo.mysql;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


@SpringBootApplication(scanBasePackages = "com.zyj.demo.mysql")
public class MysqlUpdateStockApplication implements CommandLineRunner {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void run(String... args) throws Exception {
        //初始化库存
        jdbcTemplate.execute("REPLACE  INTO sku (`id`, `stock`) VALUES ('10', '995')");
        int nThreads = 500; // 线程池数
        int totalThreads =  nThreads * 2; //总线程数
        ExecutorService pool = Executors.newFixedThreadPool(nThreads); //创建一个固定的线程池
        List<Callable<Void>> tasks = new ArrayList<>();
        for (int i = 0; i < totalThreads; i++) { //2倍于线程数的减库存任务
            tasks.add(updateStockInMysqlTask1);
        }
        long start = System.currentTimeMillis();
        List<Future<Void>> futureList = pool.invokeAll(tasks);
        boolean allMath =  futureList.stream().allMatch(f -> f.isDone());
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start));
        if (allMath) {
            pool.shutdown();
        }
    }

    private Callable<Void> updateStockInMysqlTask1 = () -> {
        //1.查询出库存。
       Long stock = jdbcTemplate.queryForObject("select stock from sku where id = 10", Long.class); //查询出库存
        System.out.println("stock:" + stock);
        //2. 如果库存 > 1 则进行 库存扣减
       if (stock > 0) {
           String sql = "update sku set stock = stock-1 where id =10 ";
           jdbcTemplate.update(sql);
       } else {
           System.out.println("库存不足");
       }
        return null;
    };

    private Callable<Void> updateStockInMysqlTask2 = () -> {
        synchronized (this) {
            Long stock = jdbcTemplate.queryForObject("select stock from sku where id = 10", Long.class); //查询出库存
            System.out.println("stock:" + stock);
            //2. 如果库存 > 1 则进行 库存扣减
            if (stock > 0) {
                String sql = "update sku set stock = stock-1 where id =10 ";
                jdbcTemplate.update(sql);
            } else {
                System.out.println("库存不足");
            }
        }
        return null;
    };

    private Callable<Void> updateStockInMysqlTask3 = () -> {
        String sql = "update sku set stock = stock-1 where id = 10 and stock > 0 ";
        int count =  jdbcTemplate.update(sql);
        if (count == 0 ) {
            System.out.println("库存不足");
        }
        return null;
    };

    public static void main(String[] args) {
        SpringApplication.run(MysqlUpdateStockApplication.class, args).close();
    }
}
